<?php

namespace common\service;

use common\exception\LogicException;
use common\model\ChatModel;
use common\model\ChatUserModel;
use common\model\DataSourceModel;
use common\model\DepartmentModel;
use common\model\OptionsModel;
use common\model\RoleModel;
use common\model\SmsVerifyModel;
use common\model\SupplierModel;
use common\model\TenantApplyModel;
use common\model\TenantAuthenticationModel;
use common\model\TenantGroupMemberModel;
use common\model\TenantGroupModel;
use common\model\TenantModel;
use common\model\TenantPositionModel;
use common\model\TenantStepCategoryLevelModel;
use common\model\TenantUserDepartmentModel;
use common\model\TenantUserModel;
use common\model\TenantUserRoleModel;
use common\model\UserModel;
use support\ErrorCode;
use support\SingletonTrait;
use teamones\Request;
use think\Exception;
use think\module\Module;
use Webman\Stomp\Client;

class TenantService
{
    use SingletonTrait;

    private $tenantUserModel;

    public function __construct()
    {
        $this->tenantUserModel = model(TenantUserModel::class);
    }

    /**
     * 数组转树结构
     * @param $list
     * @param string $pk
     * @param string $pid
     * @param string $child
     * @param int $root
     * @return array
     */
    protected function listToTree($list, $pk = 'id', $pid = 'parent_id', $child = 'children', $root = 0)
    {
        $tree = array();
        if (is_array($list)) {
            $refer = array();
            foreach ($list as $key => $data) {
                $refer[$data[$pk]] = &$list[$key];
            }

            foreach ($list as $key => $data) {
                // 判断是否存在parent
                $parentId = $data[$pid];

                if ($root == $parentId) {
                    $tree[] = &$list[$key];
                } else {
                    if (isset($refer[$parentId])) {
                        $parent = &$refer[$parentId];
                        $parent[$child][] = &$list[$key];
                    }
                }
            }
        }
        return $tree;
    }

    /**
     * 获取租户列表
     * @param $param
     * @return array
     * @throws \Exception
     */
    public function select($param)
    {
        $tenantModel = model(TenantModel::class);
        $options = [
            "order" => 'tenant.created desc',
            "fields" => 'tenant.id,tenant.name,tenant.status,tenant.created,user.name,tenant.role',
        ];
        if (array_key_exists('filter', $param)) {
            $options['filter'] = $param['filter'];
        }
        if (array_key_exists('page', $param)) {
            $options['page'] = $param['page'];
        }
        $tenantData = $tenantModel->selectData($options);
        $formatTenantData = [];
        if (!empty($tenantData['rows']) && $tenantData['total'] > 0) {
            foreach ($tenantData['rows'] as $tenantItem) {
                $tempData = $tenantItem['tenant'];
                $tempData['created_by'] = $tenantItem['user']['name'];
                $formatTenantData[] = $tempData;
            }
        }
        return [
            'total' => $tenantData['total'],
            'rows' => $formatTenantData,
        ];
    }

    /**
     * 审核通过---的租户列表
     * @param array $param
     * @param array $page
     * @return array|false|mixed|string
     */
    public function selectApprovedTenant(array $param, array $page)
    {
        //审核--通过的租户
        $where = [];
        $where['ta.status'] = 'active';

        if (!empty($param['name'])) {
            $where['tenant.name'] = ['LIKE', '%' . $param['name'] . '%'];
        }

        return model(TenantModel::class)
            ->field("tenant.id,tenant.name,tenant.status")
            ->join("tenant_authentication ta on ta.tenant_id = tenant.id")
            ->where($where)
            ->order('tenant.id desc')
            ->page($page[0], $page[1])
            ->select();
    }

    /**
     * 查询当前用户所有可用租户列表
     * @param $currentUserId
     * @return array|mixed
     * @throws \Exception
     */
    public function selectCurrentUserTenant($currentUserId)
    {
        $tenantIdList = model(TenantUserModel::class)
            ->field('tenant_id')
            ->where(['tenant_user.user_id' => $currentUserId, 'tenant_user.status' => ['NEQ', TenantUserModel::STATUS_UNEMPLOYED]])
            ->column('tenant_id');

        if (empty($tenantIdList)) {
            return [];
        }
        $resData = model(TenantModel::class)->selectData([
            'filter' => [
                'id' => ['IN', join(',', $tenantIdList)],
                'status' => 'active',
            ],
        ]);

        if (empty($resData['rows'])) {
            return [];
        }

        // 获取企业认证信息
        $tenantAuthList = model(TenantAuthenticationModel::class)->where(['tenant_id' => ['IN', join(',', $tenantIdList)]])->field(['tenant_id', 'fdd_auth_status'])->select();
        $tenantAuthMap = array_column($tenantAuthList, null, 'tenant_id');

        // 获取该用户是租户管理员的团队
        $adminTenantIds = model(TenantUserRoleModel::class)
            ->alias('t_u_r')
            ->join('role ON role.id = t_u_r.role_id')
            ->join('tenant_user ON tenant_user.id = t_u_r.tenant_user_id')
            ->where(['role.code' => RoleModel::TENANT_ADMINISTRATOR_CODE, 'tenant_user.user_id' => $currentUserId])
            ->field('tenant_user.tenant_id')
            ->column('tenant_id');

        foreach ($resData['rows'] as &$item) {
            $item['is_tenant_administrator'] = in_array($item['id'], $adminTenantIds) ? 1 : 0;
            // 企业法大大认证状态
            $item['fdd_auth_status'] = $tenantAuthMap[$item['id']] ? $tenantAuthMap[$item['id']]['fdd_auth_status'] : TenantAuthenticationModel::FDD_AUTH_STATUS_NOT_AUTH;
        }
        return $resData['rows'];
    }

    /**
     * 切换租户激活状态
     * @param $param
     * @return bool
     * @throws \Throwable
     */
    public function switchStatus($param)
    {
        $tenantModel = model(TenantModel::class);

        //团队是否存在
        $tenant = $tenantModel->field('id,status')->where($param['filter'])->find();

        if (empty($tenant)) {
            throw_strack_exception('Tenant does not exist.', ErrorCode::TENANT_NOT_EXIST);
        }

        $status = 'active';
        if ($tenant['status'] == 'active') {
            $status = 'invalid';
        }

        //修改状态
        $resData = $tenantModel->where($param['filter'])->setField('status', $status);
        if ($status == "invalid") {
            $chatService = new ChatService();
            $chatService->deleteChat(['filter' => ['link_type' => 'tenant', 'link_id' => $tenant['id']]]);
        } else {
            $this->createCompanyChat($tenant['id'], 0);
        }

        return $resData;
    }

    /**
     * 获取指定一个租户下所有部门
     * @param $param
     * @return array|null
     * @throws \Throwable
     */
    public function getDepartmentTree($param)
    {
        $tenant = model(TenantModel::class)->where($param['filter'])->find();
        $where = [];

        if (!empty($param['is_production'])) {
            $where['is_production'] = $param['is_production'];
        }
        if (!empty($param['is_management'])) {
            $where['is_management'] = $param['is_management'];
        }
        $departments = model(DepartmentModel::class)->where(['tenant_id' => $tenant['id']])->where($where)->select();

        //返回部门统计用户数
        if (!empty($param['stat_user_count'])) {
            $userCountList = $this->getDepartmentUserCount(array_column($departments, 'id'));
            foreach ($departments as &$val) {
                $val['user_count'] = $userCountList[$val['id']] ?? 0;
            }
        }

        $tenant['children'] = $this->listToTree($departments);
        return $tenant;
    }


    /**
     * 获取部门人员统计
     * @param array $departmentIds 部门ID
     * @return array
     */
    private function getDepartmentUserCount(array $departmentIds)
    {
        if (empty($departmentIds)) {
            return  [];
        }
        //排除管理员--和系统人员
        $rId = model(RoleModel::class)->where(['code' => 'admin'])->field('id')->find();
        $departmentUserCountFilter = [
            'tenant_user_department.department_id' => ['in', $departmentIds],
            'u.is_system' => "no",
            'tenant_user_role.role_id' => ["neq", $rId['id']],
        ];
        //排除离职人员
        $departmentUserCountFilter['tenant_user.status'] = ['NEQ', TenantUserModel::STATUS_UNEMPLOYED];

        $departmentUserCount = model(TenantUserDepartmentModel::class)
            ->join('tenant_user on tenant_user.id = tenant_user_department.tenant_user_id')
            ->join("user u ON tenant_user.user_id = u.id")
            ->join('tenant_user_role on tenant_user.id = tenant_user_role.tenant_user_id', 'LEFT')
            ->field("tenant_user_department.department_id,count(distinct tenant_user.id) AS user_count")
            ->where($departmentUserCountFilter)
            ->group("tenant_user_department.department_id")
            ->select();

        return array_column($departmentUserCount, 'user_count', 'department_id');

    }

    /**
     * 加入部门
     * @param $param
     * @return array
     * @throws \Exception
     */
    public function joinDepartment($param)
    {
        //查找用户是否已经加入本租户
        $tenantUserModel = model(TenantUserModel::class);
        $existUser = $tenantUserModel->where(['user_id' => $param['user_id'], 'tenant_id' => $param['tenant_id']])->find();

        if (empty($existUser)) {
            $addData = ['tenant_id' => $param['tenant_id'], 'user_id' => $param['user_id'], 'status' => 'invalid'];
            $activeTenantUser = $tenantUserModel->where(['user_id' => $param['user_id'], 'tenant_id' => $param['tenant_id'], 'status' => TenantUserModel::STATUS_ACTIVE])->find();
            if (empty($activeTenantUser)) {
                $addData['status'] = TenantUserModel::STATUS_ACTIVE;
            }
            $existUser = $tenantUserModel->addItem($addData);
        }
        $existDepartment = model(TenantUserDepartmentModel::class)->where(['tenant_user_id' => $existUser['id'], 'department_id' => $param['department_id']])->find();
        if (!empty($existDepartment)) {
            throw_strack_exception('User already exists.', ErrorCode::USER_ALREADY_EXISTS);
        }
        $resData = model(TenantUserDepartmentModel::class)->addItem(['tenant_user_id' => $existUser['id'], 'department_id' => $param['department_id']]);
        try {
            $this->autoAddCompanyChat($existUser['tenant_id'], $resData['department_id'], $existUser['user_id']);
        } catch (\Throwable $e) {
            trace("auto add department chat got exception", "ERR");
            trace(format_exception_info($e), 'ERR');
        }
        return $resData;
    }

    /**
     * 获取部门下人员
     * @param $param
     * @param bool $includeEmployed
     * @return array|null
     * @throws \Exception
     */
    public function selectDepartmentUser($param, bool $includeEmployed)
    {
        $filter = [
            'tenant_user.tenant_id' => $param['filter']['tenant_id'],
            'user.is_system' => 'no',
            'user.active' => 1,
        ];
        if (!$includeEmployed) {
            $filter['tenant_user.status'] = ['NEQ', TenantUserModel::STATUS_UNEMPLOYED];
        }
        $departmentId = $param['filter']['department_id'] ?? 0;
        $phoneOrName = $param['filter']['name_or_phone'] ?? null;
        $userIdFilter = $param['filter']['user_id'] ?? 0;
        $roleCodes = $param['filter']['role_code'] ?? "";
        $roleCodes = explode(',', $roleCodes);

        if ($departmentId) {
            $filter['department.id'] = $departmentId;
        }
        if ($userIdFilter) {
            $filter['tenant_user.user_id'] = $userIdFilter;
        }
        // 角色筛选
        if (count($roleCodes) > 0) {
            $roles = model(RoleModel::class)->where(['code' => ['IN', implode(',', $roleCodes)]])->field("id")->select();
            $roleIds = array_column($roles, 'id', 'id');
            if (count($roles) > 0) {
                $filter["role.id"] = ["IN", implode(',', $roleIds)];
            }
        }

        if (!empty($phoneOrName)) {
            $filter[] = [
                "user.name" => $phoneOrName,
                "user.phone" => $phoneOrName,
                "_logic" => "OR",
            ];
        }

        $tenantUserModel = model(TenantUserModel::class);

        if (array_key_exists('page', $param)) {
            $page = join(',', $param['page']);
        } else {
            $maxPageSize = C("database.database_max_select_rows");
            $page = "1, {$maxPageSize}";
        }

        // 获取总行数
        $total = $tenantUserModel
            ->join("user ON user.id = tenant_user.user_id")
            ->join('tenant_user_department on tenant_user_department.tenant_user_id = tenant_user.id', 'LEFT')
            ->join('tenant_user_role on tenant_user_role.tenant_user_id = tenant_user.id', 'LEFT')
            ->join("role ON role.id = tenant_user_role.role_id", 'LEFT')
            ->join("department ON department.id = tenant_user_department.department_id", 'LEFT')
            ->where($filter)
            ->count();

        $data = [];
        if ($total > 0) {
            $fields = [
                'tenant_user.id', 'tenant_user.user_id', 'tenant_user.tenant_id',
                'tenant_user.status', 'tenant_user.created',
                'user.name', 'user.phone', 'user.email',
                'tenant_user.tenant_position_id as tenant_position_id',
            ];
            $data = $tenantUserModel
                ->join("user ON user.id = tenant_user.user_id")
                ->join('tenant_user_department on tenant_user_department.tenant_user_id = tenant_user.id', 'LEFT')
                ->join('tenant_user_role on tenant_user_role.tenant_user_id = tenant_user.id', 'LEFT')
                ->join("role ON role.id = tenant_user_role.role_id")
                ->join("department ON department.id = tenant_user_department.department_id")
                ->field($fields)
                ->where($filter)
                ->page($page)
                ->group('tenant_user.id')
                ->order('created desc')
                ->select();
            $tenantUserIdList = array_column($data, 'id');
            $userDepartmentRoleInfoList = TenantUserService::getInstance()->getTenantUserListDepartmentRole($tenantUserIdList);

            //获取岗位列表
            $capacityInfo = CapacityService::getInstance()->getCapacityConfig(0, $param['filter']['tenant_id']);
            $positionList = array_column($capacityInfo['list'], null, 'id');

            foreach ($data as &$datum) {
                //岗位名称
                $datum['tenant_position_name'] = $positionList[$datum['tenant_position_id']]['name'] ?? '';

                $datum['department_info'] = $datum['role_info'] = [];
                if (isset($userDepartmentRoleInfoList[$datum['id']])) {
                    $datum = array_merge($datum, $userDepartmentRoleInfoList[$datum['id']]);
                }
            }
        }

        return [
            "total" => $total,
            "rows" => $data,
        ];
    }

    /**
     * 删除部门人员
     * @param $param
     * @return array
     * @throws \Throwable
     */
    public function deleteDepartmentUser($param)
    {
        $tenantUserModel = model(TenantUserModel::class);

        $tenantUser = $tenantUserModel->where($param['filter'])->find();

        if (empty($tenantUser)) {
            throw_strack_exception('User does not exist.', ErrorCode::USER_NOT_EXIST);
        }
        // 成员部门信息
        $tenantUserDepartmentList = model(TenantUserDepartmentModel::class)->where(['tenant_user_id' => $tenantUser['id']])->select();
        // 成员角色信息
        $tenantUserRoleList = model(TenantUserRoleModel::class)->where(['tenant_user_id' => $tenantUser['id']])->select();

        $departmentIdList = array_column($tenantUserDepartmentList, 'department_id');
        // 供应商列表移除
        $supplierModel = model(SupplierModel::class);
        $supplier = $supplierModel->field('id')->where(['user_id' => $tenantUser['user_id'], 'type' => 'inside', 'tenant_id' => $tenantUser['tenant_id']])->find();

        // 租户自动激活信息查询
        $userId = $tenantUser['user_id'];
        $activeTenantUser = $tenantUserModel->where(['user_id' => $userId, 'status' => 'active', 'tenant_id' => ['NEQ', $tenantUser['tenant_id']]])->find();
        $needActiveTenantUserId = 0;
        if (empty($activeTenantUser)) {
            $firstTenantUser = $tenantUserModel->where(['user_id' => $userId, 'tenant_id' => ['NEQ', $tenantUser['tenant_id']]])->order("id desc")->find();
            if (!empty($firstTenantUser)) {
                $needActiveTenantUserId = $firstTenantUser['id'];
            }
        }

        $tenantUserModel->startTrans();
        try {
            // 删除供应商信息
            if (!empty($supplier)) {
                $supplierModel->where(['id' => $supplier['id']])->delete();
            }
            // 删除租户成员
            $resData = $tenantUserModel->where(['id' => $tenantUser['id']])->delete();
            if (!$resData) {
                throw_strack_exception($tenantUserModel->getError(), $tenantUserModel->getErrorCode());
            }
            // 删除租户成员部门
            if (!empty($tenantUserDepartmentList)) {
                $resData = model(TenantUserDepartmentModel::class)
                    ->where(['id' => implode(',', array_column($tenantUserDepartmentList, 'id'))])
                    ->delete();
                if (!$resData) {
                    throw_strack_exception(model(TenantUserDepartmentModel::class)->getError(), $tenantUserModel->getErrorCode());
                }
            }
            // 删除租户成员角色
            if (!empty($tenantUserRoleList)) {
                $resData = model(TenantUserRoleModel::class)
                    ->where(['id' => implode(',', array_column($tenantUserRoleList, 'id'))])
                    ->delete();
                if (!$resData) {
                    throw_strack_exception(model(TenantUserRoleModel::class)->getError(), $tenantUserModel->getErrorCode());
                }
            }
            // 激活其他可用租户
            if (!empty($needActiveTenantUserId)) {
                $tenantUserModel->where(['id' => $needActiveTenantUserId])->save(['status' => 'active']);
            }
            // 当用户不存在部门时传0
            $departmentIdList = empty($departmentIdList) ? [0] : $departmentIdList;
            // 公司群移除成员
            $this->deleteUserFromCompanyDepartmentChat($tenantUser['tenant_id'], ['IN', $departmentIdList], $tenantUser['user_id']);
            $tenantUserModel->commit();
            try {
                $centrifugoService = CentrifugalService::getInstance();
                $centrifugoService->sendDataToMineChannel([
                    'event_key' => "be_removed_from_tenant",
                    'event_data' => [
                        "tenant_id" => $tenantUser['tenant_id'],
                        'user_id' => $userId,
                    ],
                ], $userId);
            } catch (\Throwable $e) {
                trace(format_exception_info($e), 'ERR');
            }
            return ["ids" => $tenantUser['id']];
        } catch (\Throwable $e) {
            $tenantUserModel->rollback();
            throw $e;
        }
    }

    /**
     * 批量设置角色
     * @param $param
     * @return bool
     * @deprecated 2023年5月19日 角色权限拆分了
     */
    public function saveRole($param)
    {

        $tenantUserModel = model(TenantUserModel::class);

        $filter = $param['param']['filter'];

        try {
            $tenantUser = $tenantUserModel->where($filter)->select();
            if (empty($tenantUser)) {
                throw new LogicException('User does not exist.', ErrorCode::USER_NOT_EXIST);
            }

            $supplierModel = model(SupplierModel::class);
            $supplier = $supplierModel->field('id')->where(['user_id' => ['IN', join(',', array_column($tenantUser, 'user_id'))], 'type' => 'inside', 'tenant_id' => $tenantUser[0]['tenant_id']])->select();

            if (!empty($supplier)) {
                $supplierModel->where(['id' => ['IN', join(',', array_column($supplier, 'id'))]])->delete();
            }

            $roleModel = model(RoleModel::class);
            $headman = $roleModel->field('id')->where(['code' => 'headman'])->find();

            foreach ($tenantUser as $value) {
                if ($param['data']['role_id'] == $headman['id']) {
                    $insideSupplier = [
                        "user_id" => $value["user_id"],
                        "type" => "inside",
                        "tenant_id" => $value["tenant_id"],
                        "from_tenant_id" => $value["tenant_id"],
                        "step_ids" => "",
                    ];
                    $supplierModel->addItem($insideSupplier);
                }

                //查找用户是否加入多个租户
                $hasTenantUser = $tenantUserModel->field('user_id')->where(['user_id' => $value["user_id"], 'status' => 'active'])->find();
                if (empty($hasTenantUser)) {
                    $needActiveUser[] = $value["user_id"];
                }
            }
            $resData = $tenantUserModel->where($filter)->save($param['data']);

            //激活用户
            if (!empty($needActiveUser)) {
                $tenantUserModel->where(['user_id' => ['IN', join(',', $needActiveUser)], 'tenant_id' => $tenantUser[0]['tenant_id']])->setField('status', 'active');
            }

            return $resData;
        } catch (\Exception $e) {
            throw_strack_exception($e->getMessage(), $e->getCode());
        }
    }

    /**
     * 批量设置部门
     * @param $param
     * @return array
     * @deprecated 2023年5月19日 部门和角色进行了拆分
     */
    public function saveDept($param)
    {
        $tenantUserModel = model(TenantUserModel::class);
        try {
            $tenantUsers = $tenantUserModel->where($param['param']['filter'])->select();
            $tenantUsers = array_column($tenantUsers, null, 'id');
            $resData = [];
            foreach ($tenantUsers as $tenantUser) {
                $data = $param['data'];
                $data['id'] = $tenantUser['id'];
                $resData[] = $tenantUserModel->modifyItem($data);
            }
            $resData = array_column($resData, null, 'id');

            $this->autoSwitchDepartmentChat($tenantUsers, $resData);
            return $resData;

        } catch (\Exception $e) {
            throw_strack_exception('update failure.', ErrorCode::DEPARTMENT_UPDATE_FAILURE);
        }
    }

    /**
     * 查询当前用户租户里的用户 根据角色筛选
     * @param $tenantId
     * @param $params
     * @param $includeEmployed
     * @return array
     * @throws \Exception
     */
    public function selectTenantUser($tenantId, $params, $includeEmployed): array
    {
        $filter = $params['param']['filter'] ?? [];
        $filter['tenant_user.tenant_id'] = $tenantId;
        $filter[] = ['user.phone' => ['NEQ', 'admin']];
        // 如果没有指定筛选什么类型的用户 那么就默认不查询系统用户
        if (!isset($filter['user.is_system'])) {
            $filter['user.is_system'] = 'no';
        }
        if (!empty($filter["step_category_id_list"])) {
            $stepCategoryIdList = explode(",", $filter["step_category_id_list"]);
            $stepCategoryIdFilter = [];
            foreach ($stepCategoryIdList as $stepCategoryIdItem) {
                $stepCategoryIdFilter[] = ["department.step_category_ids" => ["FIND_IN_SET", $stepCategoryIdItem]];
            }
            if (count($stepCategoryIdFilter) > 1) {
                $stepCategoryIdFilter["_logic"] = "OR";
            }
            $filter[] = $stepCategoryIdFilter;
            unset($filter["step_category_id_list"]);
        }
        // 不包含离职筛选
        if (!$includeEmployed) {
            $filter['tenant_user.status'] = ['NEQ', TenantUserModel::STATUS_UNEMPLOYED];
        }

        $tenantUserIdList = model(TenantUserModel::class)
            ->join("user ON tenant_user.user_id = user.id")
            ->join('tenant_user_department on tenant_user.id = tenant_user_department.tenant_user_id', 'LEFT')
            ->join('tenant_user_role on tenant_user.id = tenant_user_role.tenant_user_id', 'LEFT')
            ->join("role ON tenant_user_role.role_id = role.id", "LEFT")
            ->join("department ON tenant_user_department.department_id = department.id", "LEFT")
            ->where($filter)
            ->field('tenant_user.id')
            ->group('tenant_user.id')
            ->column('id');
        if (empty($tenantUserIdList)) {
            return [];
        }
        $queryFields = [
            'tenant_user.id as tenant_user_id',
            'tenant_user.user_id as id',
            'tenant_user.user_id as user_id',
            'tenant_user.tenant_position_id as tenant_position_id',
            'user.name', 'user.phone', 'user.email',
        ];
        $data = model(TenantUserModel::class)
            ->join('user on user.id = tenant_user.user_id')
            ->where(['tenant_user.id' => ['IN', implode(',', $tenantUserIdList)]])
            ->field($queryFields)
            ->select();

        $userIdData = array_column($data, 'id', 'id');
        $avatarMap = UserService::getInstance()->getUserAvatar($userIdData);

        $userRoleDepartmentInfoList = TenantUserService::getInstance()->getTenantUserListDepartmentRole($tenantUserIdList);

        //获取岗位列表
        $capacityInfo = CapacityService::getInstance()->getCapacityConfig(0, $tenantId);
        $positionList = array_column($capacityInfo['list'], null, 'id');

        foreach ($data as &$user) {
            $user['avatar'] = $avatarMap[$user['id']] ?? '';
            $user['department_info'] = $user['role_info'] = [];
            //岗位名称
            $user['tenant_position_name'] = $positionList[$user['tenant_position_id']]['name'] ?? '';

            if (isset($userRoleDepartmentInfoList[$user['tenant_user_id']])) {
                $user = array_merge($user, $userRoleDepartmentInfoList[$user['tenant_user_id']]);
            }
        }

        return $data;
    }

    /**
     * 切换租户
     * @param int $userId
     * @param $param
     * @return bool
     */
    public function switchToTenant(int $userId, $param)
    {
        $tenantUserModel = model(TenantUserModel::class);

        //检查要切换到的租户
        $tenantUserSwitchTo = $tenantUserModel->field("id")
            ->where($param['filter'])
            ->where(['user_id' => $userId])
            ->select();

        if (empty($tenantUserSwitchTo)) {
            throw_strack_exception("can`t found a tenant which you specified", ErrorCode::THE_SPECIFIED_TENANT_NOT_FOUND);
        }
        $tenantUserSwitchToId = array_column($tenantUserSwitchTo, 'id');
        //将激活的租户 设置为未激活
        $activeTenant = $tenantUserModel
            ->field("id")
            ->where(['user_id' => $userId, 'status' => 'active'])
            ->select();
        if (!empty($activeTenant)) {
            // 过滤掉要切换的租户
            $activeTenantIdList = array_column($activeTenant, 'id');
            $activeTenantIdList = array_filter($activeTenantIdList, function ($item) use ($tenantUserSwitchToId) {
                return !in_array($item, $tenantUserSwitchToId);
            });
            if (count($activeTenantIdList)) {
                $tenantUserModel->where(['id' => ['IN', join(',', $activeTenantIdList)]])
                    ->setField('status', 'invalid');
            }
        }

        //激活租户
        return $tenantUserModel->where(['id' => ['IN', $tenantUserSwitchToId],])->save(['status' => 'active']);
    }

    /**
     * 用户申请加入租户
     * @param $userId
     * @param $tenantId
     * @param $reasons
     * @return array|bool
     * @throws \Exception
     */
    public function applyAppendToTenant($userId, $tenantId, $reasons)
    {
        $tenantApplyModel = model(TenantApplyModel::class);

        // 校验是否有审核中的记录
        $exitData = $tenantApplyModel->where(['user_id' => $userId, 'status' => TenantApplyModel::STATUS_IN_REVIEW])->field(['id'])->find();
        if (!empty($exitData)) {
            throw_strack_exception('Only one team can be applied at the same time.', ErrorCode::ONLY_ONE_TEAM_CAN_BE_APPLIED_AT_THE_SAME_TIME);
        }

        // 校验用户是否已在该团队
        $isExistsUser = model(TenantUserModel::class)->where(['user_id' => $userId, 'tenant_id' => $tenantId])->field(['id'])->find();
        if (!empty($isExistsUser)) {
            throw_strack_exception('The user is already in the tenant.', ErrorCode::DATA_ALREADY_EXISTS);
        }

        $resData = $tenantApplyModel->addItem([
            'user_id' => $userId,
            'tenant_id' => $tenantId,
            'reasons' => $reasons,
        ]);

        if (!$resData) {
            // 通用创建失败错误码 001
            throw_strack_exception($tenantApplyModel->getError(), ErrorCode::FAILED_TO_APPLY_TO_JOIN_TEAM);
        } else {
            // 返回成功数据
            return $resData;
        }
    }

    /**
     * 同意用户加入租户
     * @param $param
     * @return array|bool
     * @throws \Exception
     */
    public function agreeAppendUserToTenant($param)
    {
        $tenantApplyModel = model(TenantApplyModel::class);
        // 只能申请中的才能被审核
        $tenantApplyData = $tenantApplyModel->where(['id' => $param['tenant_apply_id'], 'status' => TenantApplyModel::STATUS_IN_REVIEW])->find();
        if (empty($tenantApplyData)) {
            throw_strack_exception('User application information does not exist.', ErrorCode::USER_APPLICATION_INFO_NOT_EXIST);
        }
        $tenantUserModel = model(TenantUserModel::class);
        $resData = $tenantUserModel->addItem([
            'user_id' => $tenantApplyData['user_id'],
            'tenant_id' => $tenantApplyData['tenant_id'],
            'status' => $param['status'],
        ]);
        if ($resData === false) {
            throw new LogicException('add tenant user error:' . $tenantUserModel->getError(), $tenantUserModel->getErrorCode());
        }

        $supplierModel = model(SupplierModel::class);
        $supplier = $supplierModel->field('id')->where(['user_id' => $tenantApplyData['user_id'], 'type' => 'inside', 'tenant_id' => $tenantApplyData['tenant_id']])->find();
        if (!empty($supplier)) {
            $supplierModel->where(['id' => $supplier['id']])->delete();
        }

        if ($param['status'] == "active") {
            //如果存在激活的租户 那么都设置为未激活
            $tenantUserIdData = $tenantUserModel->where([
                'user_id' => $tenantApplyData['user_id'],
                'status' => 'active',
                'id' => ['neq', $resData['id']],
            ])->select();
            if (!empty($tenantUserIdData)) {
                foreach ($tenantUserIdData as $tenantUser) {
                    $tenantUserModel->save([
                        'id' => $tenantUser['id'],
                        'status' => "invalid",
                    ]);
                }
            }
        } else {
            // 如果没有激活的租户 那么激活申请租户
            $tenantUserIdData = $tenantUserModel->where(['user_id' => $tenantApplyData['user_id'], 'status' => 'active'])->find();
            if (!empty($tenantUserIdData)) {
                $tenantUserModel->save([
                    'id' => $resData['id'],
                    'status' => "active",
                ]);
            }
        }

        if (!$resData) {
            // 通用创建失败错误码 001
            throw_strack_exception($tenantUserModel->getError(), ErrorCode::FAILED_TO_AGREE_USER_TO_JOIN_TEAM);
        }

        // 返回成功数据
        $tenantApplyModel->where(['id' => $param['tenant_apply_id']])->save(['status' => TenantApplyModel::STATUS_PASS]); // 将申请状态更新为已审核
        $this->autoAddCompanyChat($resData['tenant_id'], 0, $resData['user_id']);
        return $resData;
    }

    /**
     * 拒绝用户加入租户
     * @param $tenantApplyId
     * @return array
     */
    public function refuseAppendUserToTenant($tenantApplyId)
    {
        $tenantApplyModel = model(TenantApplyModel::class);
        // 将状态更新为已拒绝
        $resData = $tenantApplyModel->where(['id' => $tenantApplyId])->save(['status' => TenantApplyModel::STATUS_REJECTED]);

        if (!$resData) {
            // 通用删除失败错误码 003
            throw_strack_exception($tenantApplyModel->getError(), ErrorCode::FAILED_TO_REFUSE_USER_TO_JOIN_TEAM);
        }
        // 返回成功数据
        return ['ids' => $tenantApplyId];
    }

    /**
     * 查询指定租户申请用户信息
     * @param $tenantId
     * @return mixed
     */
    public function getTenantApplyUserList($tenantId)
    {
        $tenantApplyModel = model(TenantApplyModel::class);
        $tenantData = $tenantApplyModel->alias('apply')
            ->join("LEFT JOIN user ON user.id = apply.user_id")
            // 只获取审核中的申请列表
            ->where(['apply.tenant_id' => $tenantId, 'apply.status' => TenantApplyModel::STATUS_IN_REVIEW])
            ->field('apply.id,user.name,user.phone,apply.user_id,apply.tenant_id,apply.reasons,apply.created')
            ->select();

//        foreach ($tenantData as &$tenantItem) {
//            $tenantItem['created'] = get_format_date($tenantItem['created'], 1);
//        }

        return !empty($tenantData) ? $tenantData : [];
    }

    /**
     * 获取当前用户申请
     * @param $userId
     * @return array|false|mixed|string|null
     */
    public function getUserTenantApply($userId)
    {
        return model(TenantApplyModel::class)->alias('apply')
            ->join("LEFT JOIN tenant ON tenant.id = apply.tenant_id")
            ->where(['apply.user_id' => $userId])
            ->field('apply.id,tenant.name,apply.tenant_id,apply.created,apply.status')
            // 取最新的一条记录
            ->order('apply.id DESC')
            ->find();
    }

    /**
     * 自动加入公司/部门聊天
     * @param $tenantId
     * @param $departmentId
     * @param $userId
     * @throws \Exception
     */
    public function autoAddCompanyChat($tenantId, $departmentId, $userId)
    {
        // 支持数组id
        if (is_array($departmentId)) {
            $departmentId = ['IN', $departmentId];
        }
        $chatList = model(ChatModel::class)
            ->where([
                [
                    'link_id' => $departmentId,
                    'link_type' => 'department',
                ],
                [
                    'link_id' => $tenantId,
                    'link_type' => 'tenant',
                ],
                '_logic' => 'OR',
            ])
            ->select();

        $companyChat = array_filter($chatList, function ($item) {
            return $item['link_type'] == 'tenant';
        });
        //  公司群不存在 创建公司群
        if (empty($companyChat)) {
            $this->createCompanyChat($tenantId, 0);
        }
        $departmentChat = array_filter($chatList, function ($item) {
            return $item['link_type'] == 'department';
        });
        // 部门群不存在创建部门群 异步处理 会话创建和成员拉入
        if (empty($departmentChat)) {
            $departmentList = model(DepartmentModel::class)->where(['id' => $departmentId])->select();
            if (!empty($departmentList)) {
                foreach ($departmentList as $department) {
                    $departmentService = new DepartmentService();
                    $departmentService->autoCreateDepartmentChat($department);
                }
            }
        }
        foreach ($chatList as $chat) {
            $chatUserData = [
                'chat_global_id' => $chat['global_id'],
                'user_id' => $userId,
            ];
            $chatUserModel = model(ChatUserModel::class);
            $chatUser = $chatUserModel->where($chatUserData)->find();
            //存在历史chatUser  直接启用
            if (!empty($chatUser['is_leave']) && $chatUser['is_leave'] == 'yes') {
                $chatUserModel->modifyItem([
                    'id' => $chatUser['id'],
                    'is_leave' => 'no',
                ]);
                continue;
            }
            //添加
            $res = $chatUserModel->addItem($chatUserData);
            if ($res === false && $chatUserModel->getErrorCode() !== \think\exception\ErrorCode::DATA_ALREADY_EXISTS) {
                throw new LogicException($chatUserModel->getError(), is_numeric($chatUserModel->getErrorCode()) ? $chatUserModel->getErrorCode() : ErrorCode::AUTO_JOIN_DEPARTMENT_CHAT_FAILURE);
            }
        }
    }

    /**
     * 删除用户部门聊天
     * @param $tenantId
     * @param $departmentId
     * @param $userId
     */
    private function deleteUserFromCompanyDepartmentChat($tenantId, $departmentId, $userId)
    {
        $chatList = model(ChatModel::class)
            ->where([
                [
                    'link_id' => $tenantId,
                    'link_type' => 'tenant',
                ],
                [
                    'link_id' => $departmentId,
                    'link_type' => 'department',
                ],
                '_logic' => 'OR',
            ])
            ->field("global_id")
            ->select();
        $chatList = array_column($chatList, 'global_id', 'global_id');

        $filter = [
            'chat_global_id' => ['IN', implode(',', $chatList)],
            'user_id' => $userId,
        ];
        $chatUserService = new ChatUserService();
        $chatUserService->deleteWithOutAuth($filter);
    }

    /**
     * 从部门聊天移除用户
     * @param int $userId
     * @param array $departmentIdList
     */
    public function deleteUserFromDepartmentChat(int $userId, array $departmentIdList)
    {
        $chatList = model(ChatModel::class)
            ->where(['link_id' => ['IN', $departmentIdList], 'link_type' => 'department',])
            ->field("global_id")
            ->select();
        $chatList = array_column($chatList, 'global_id', 'global_id');
        $filter = [
            'chat_global_id' => ['IN', implode(',', $chatList)],
            'user_id' => $userId,
        ];
        $chatUserService = new ChatUserService();
        $chatUserService->deleteWithOutAuth($filter);
    }

    /**
     * 切换用户部门 自动切换聊天
     * @param array $tenantUsers
     * @param array $changeTenantUsers
     * @throws Exception
     */
    private function autoSwitchDepartmentChat(array $tenantUsers, array $changeTenantUsers)
    {
        foreach ($changeTenantUsers as $tenantUserId => $changeTenantUser) {
            //修改失败
            if ($changeTenantUser === false) {
                continue;
            }
            $oldDepartmentId = $tenantUsers[$tenantUserId]['department_id'];
            $newDepartmentId = $changeTenantUser['department_id'];
            //没有修改部门
            if ($oldDepartmentId == $newDepartmentId) {
                continue;
            }
            //删除老会话
            $tenantUser = $tenantUsers[$tenantUserId];
            $this->deleteUserFromCompanyDepartmentChat($tenantUser['tenant_id'], $tenantUser['department_id'], $tenantUser['user_id']);
            //加入新会话
            $this->autoAddCompanyChat($changeTenantUser['tenant_id'], $changeTenantUser['department_id'], $changeTenantUser['user_id']);
        }
    }

    /**
     * 创建公司会话
     * @param int $tenantId
     * @param int $owner
     * @throws \Exception
     */
    public function createCompanyChat(int $tenantId, int $owner)
    {
        $tenant = model(TenantModel::class)->find($tenantId);
        $chat = [
            'name' => $tenant['name'],
            'type' => "group",
            'link_id' => $tenantId,
            'link_type' => "tenant",
            'from_tenant_id' => $tenantId,
            'to_tenant_id' => 0,
        ];

        $chatOld = model(ChatModel::class)->where(['link_type' => 'tenant', 'link_id' => $tenant['id']])->find();
        $chatUsers = model(TenantUserModel::class)->where(['tenant_id' => $tenantId])->field("user_id")->distinct(true)->column('user_id');
        if (empty($chatOld)) {
            Client::send('create_chat', build_queue_data_with_xu([
                'chat' => $chat,
                'chat_users' => $chatUsers,
                'owner' => $owner,
            ]));
            return;
        }

        //  激活聊天
        if ($chatOld['is_delete'] == "yes") {
            model(ChatModel::class)->save([
                'id' => $chatOld['id'],
                'is_delete' => 'no',
            ]);
        }

        $chatUserService = new ChatUserService();
        $chatUserService->inviteUser([
            'user_id' => $chatUsers,
            'chat_global_id' => $chatOld['global_id'],
        ]);

    }

    /**
     * 获得租户 fdd_customer_id
     * @param $filter
     * @return mixed
     */
    public function getFddCustomerId($filter)
    {
        $tenant = model(TenantModel::class)->where($filter)->find();
        if (empty($tenant)) {
            throw_strack_exception('Tenant does not exist.', ErrorCode::TENANT_NOT_EXIST);
        }
        if (empty($tenant['fdd_customer_id'])) {
            throw_strack_exception("missing fdd_customer_id", ErrorCode::MISSING_FDD_CUSTOMER_ID);
        }
        return $tenant['fdd_customer_id'];
    }

    /**
     * 查询租户详情  (包含认证信息 认证等级)
     * @param $tenantId
     * @return array|false|mixed|string|null
     */
    public function getTenantDetail($tenantId)
    {
        $data = model(TenantModel::class)
            ->where(['tenant.id' => $tenantId])
            ->find();

        if (empty($data)) {
            return null;
        }
        $tenantAuthenticationData = model(TenantAuthenticationModel::class)
            ->where(['tenant_id' => $tenantId])
            ->field("fdd_cert_status,fdd_auth_status_desc,reasons_for_failure,fdd_auth_url,fdd_transaction_no", true)
            ->find();
        $authCreatedBy = $tenantAuthenticationData['created_by'] ?? 0;
        if (!empty($tenantAuthenticationData)) {
            CommonService::getFormatAttrData(model(TenantAuthenticationModel::class), $tenantAuthenticationData);
        }
        if ($authCreatedBy) {
            $data['creator'] = model(UserModel::class)->field('id,name,phone,email')->find($authCreatedBy);
        }
        //每个供应商 对应不同分类的等级数据
        $data['authentication'] = $tenantAuthenticationData;
        $data['level_data'] = model(TenantStepCategoryLevelModel::class)
            ->where([
                'tenant_id' => $tenantId,
            ])
            ->field("uuid,created,updated,created_by", true)
            ->select();;

        return $data;
    }

    /**
     * 更新用户部门信息
     * @param int $tenantId
     * @param int $userId
     * @param array $departmentRoleData
     * @return array
     * @throws \Throwable
     * @deprecated 2023年5月17日
     */
    public function saveUserDepartment(int $tenantId, int $userId, array $departmentRoleData)
    {
        // 判断用户之前的激活的租户是那个
        $activeTenantUser = $this->tenantUserModel->where(['user_id' => $userId, 'status' => 'active'])->field('tenant_id')->find();
        if (empty($activeTenantUser)) {
            $isActive = true;
        } else {
            $isActive = $activeTenantUser['tenant_id'] == $tenantId;
        }
        $tenantUsers = $this->tenantUserModel->where(['tenant_id' => $tenantId, 'user_id' => $userId])->select();
        // 职位信息
        $positionIdList = array_column($tenantUsers, 'tenant_position_id');
        $positionIdList = array_unique(array_filter($positionIdList, function ($item) {
            return intval($item) > 0;
        }));
        $position = null;
        if (count($positionIdList) > 0) {
            $positionIdList = array_unique($positionIdList);
            $position = model(TenantPositionModel::class)->where(['id' => ['IN', $positionIdList]])->find();
        }
        // 检索出退出了的部门
        $oldDepartmentIdList = array_column($tenantUsers, 'department_id', 'department_id');
        $newDepartmentIdList = array_column($departmentRoleData, 'department_id', 'department_id');
        $needDeleteDepartmentIdList = array_diff($oldDepartmentIdList, $newDepartmentIdList);

        $res = [];
        $status = $isActive ? 'active' : "invalid";
        $positionId = !empty($position) ? $position['id'] : 0;

        // 比对数据 筛选出需要删除/添加/更新的数据
        $needAddDepartmentChat = [];
        $updateData = [];
        $addData = [];
        $departmentRoleData = array_column($departmentRoleData, null, 'department_id');
        $tenantUsers = array_column($tenantUsers, null, 'department_id');
        $needDeleteTenantUserIdList = [];
        if (count($needDeleteDepartmentIdList)) {
            $needDeleteTenantUserList = array_filter($tenantUsers, function ($item) use ($needDeleteDepartmentIdList) {
                return in_array($item['department_id'], $needDeleteDepartmentIdList);
            });
            if (count($needDeleteTenantUserList) > 0) {
                $needDeleteTenantUserIdList = array_column($needDeleteTenantUserList, 'id');
            }
        }

        foreach ($departmentRoleData as $departmentId => $departmentRoleDatum) {
            if (array_key_exists($departmentId, $tenantUsers)) {
                $updateData[] = [
                    'id' => $tenantUsers[$departmentId]['id'],
                    'status' => $status,
                    'role_id' => $departmentRoleDatum['role_id'],
                    'tenant_position_id' => $positionId,
                ];
            } else {
                // 需要添加部门成员信息
                $needAddDepartmentChat[] = $departmentId;
                $departmentRoleDatum['tenant_id'] = $tenantId;
                $departmentRoleDatum['user_id'] = $userId;
                $departmentRoleDatum['status'] = $status;
                $departmentRoleDatum['tenant_position_id'] = $positionId;
                $departmentRoleDatum['created'] = time();
                $addData[] = $departmentRoleDatum;
            }
        }
        $this->tenantUserModel->startTrans();
        try {
            if (count($needDeleteTenantUserIdList) > 0) {
                $this->tenantUserModel->where(['id' => ['IN', $needDeleteTenantUserIdList]])->delete();
            }
            if (count($needDeleteDepartmentIdList)) {
                // 从需要删除的部门删除
                $this->deleteUserFromDepartmentChat($userId, $needDeleteDepartmentIdList);
            }
            if (count($addData) > 0) {
                $this->tenantUserModel->addAll($addData);
            }
            if (count($updateData) > 0) {
                foreach ($updateData as $updateItem) {
                    $this->tenantUserModel->save($updateItem);
                }
            }
            if (count($needAddDepartmentChat)) {
                $this->autoAddCompanyChat($tenantId, $needAddDepartmentChat, $userId);
            }
            $this->tenantUserModel->commit();
            return $res;
        } catch (\Throwable $e) {
            $this->tenantUserModel->rollback();
            throw $e;
        }
    }


    /**
     * 获取指定部门的工序列表
     * @param array $departmentIdList
     * @return array
     */
    public function getDepartmentStepIdList(array $departmentIdList)
    {
        $departmentList = model(DepartmentModel::class)->where(['id' => ['IN', $departmentIdList]])->field('step_category_ids')->select();
        $res = [];
        foreach ($departmentList as $department) {
            if (strstr($department['step_category_ids'], ',') !== false) {
                $stepCategoryIdList = explode(',', $department['step_category_ids']);
                if (count($stepCategoryIdList)) {
                    foreach ($stepCategoryIdList as $stepCategoryId) {
                        $res[$stepCategoryId] = (int)$stepCategoryId;
                    }
                }
            } elseif (($stepCategoryId = intval($department['step_category_ids'])) && $stepCategoryId > 0) {
                $res[$stepCategoryId] = $stepCategoryId;
            }
        }

        return array_values($res);
    }

    /**
     * 设置用户职位
     * @param array $userIdList
     * @param int $tenantId
     * @param string $tenantPositionId
     * @return bool|int|string
     * @throws \Exception
     */
    public function setUserPosition(array $userIdList, int $tenantId, string $tenantPositionId)
    {
        $tenantUserIdList = model(TenantUserModel::class)
            ->where([
                'tenant_id' => $tenantId,
                'user_id' => ['IN', $userIdList],
            ])
            ->field('id')
            ->column('id');
        if (count($tenantUserIdList) === 0) {
            throw new LogicException("Parameter error", ErrorCode::REQUEST_PARAM_ERROR);
        }
        //判断岗位是否正确
        $capacityInfo = CapacityService::getInstance()->getCapacityConfig(0, $tenantId);
        $positionList = array_column($capacityInfo['list'], 'id');
        if ($tenantPositionId) {
            foreach (explode(',', $tenantPositionId) as $val) {
                if (!in_array($val, $positionList)) {
                    throw new LogicException("Position parameter error", ErrorCode::REQUEST_PARAM_ERROR);
                }
            }
        }

        //更新岗位信息
        $rt = model(TenantUserModel::class)->where(['id' => ['IN', $tenantUserIdList]])->save(['tenant_position_id' => $tenantPositionId]);
        //异步更新--产能统计
        if ($rt) {
            $queueData = [
                'tenant_id' => $tenantId,
                'user_ids' => $userIdList,
                'tenant_position_id' => $tenantPositionId,
            ];
            Client::send('sync_capacity_pool', build_queue_data_with_xu($queueData));
        }
        return $rt;
    }

    /**
     * 导入用户岗位
     * @param array $userPositionList 导入的数据
     * @param int   $tenantId 租户ID
     * @return int
     */
    public function importUserPosition(array $userPositionList, int $tenantId)
    {
        //获取岗位列表
        $capacityInfo = CapacityService::getInstance()->getCapacityConfig(0, $tenantId);
        $positionList = array_column($capacityInfo['list'], null, 'name');

        //用户列表
        $userNames = array_unique(array_column($userPositionList,'user_name'));
        $userList = model(UserModel::class)->field('id,name')->where(['name' => ['IN', $userNames]])->select();
        $userList = array_column($userList, null, 'name');

        foreach ($userPositionList as &$val) {
            //判断岗位
            $val['position_id'] = $positionList[$val['position_name']]['id'] ?? 0;
            if (empty($val['position_id'])) {
                throw new LogicException("岗位名错误:".$val['position_name'], ErrorCode::POSITION_NAME_ERROR);
            }
            //判断用户名是否正确
            $val['user_id'] = $userList[$val['user_name']]['id'] ?? 0;
            if (empty($val['user_id'])) {
                throw new LogicException("用户名错误:".$val['user_name'], ErrorCode::USER_NAME_ERROR);
            }
        }
        //批量设置用户岗位
        $newList = arrayGroup($userPositionList, 'position_id', 'user_id');
        foreach ($newList as $newVal) {
            $this->setUserPosition(explode(',', $newVal['user_id']), $tenantId, $newVal['position_id']);
        }
        return 1;
    }

    /**
     * 租户部门人员角色存在检查
     * @param $param
     * @return array
     */
    public function checkDepartmentUserExist($param)
    {
        $tenantUserList = model(TenantUserModel::class)
            ->join('tenant_user_department on tenant_user_department.tenant_user_id = tenant_user.id', 'LEFT')
            ->join('tenant_user_role on tenant_user_role.tenant_user_id = tenant_user.id', 'LEFT')
            ->join("role ON role.id = tenant_user_role.role_id", 'LEFT')
            ->join("department ON department.id = tenant_user_department.department_id", 'LEFT')
            ->where($param['filter'])
            ->group('department.id')
            ->field('department.id')
            ->select();
        return array_column($tenantUserList, 'id');
    }

    /**
     * 获得租户部门信息,平铺的部门信息,包含parent ref关系
     * @param int $tenantId
     * @return array
     */
    private function getTenantDepartmentParentRefData(int $tenantId)
    {
        $departmentList = model(DepartmentModel::class)->where(['tenant_id' => $tenantId])->field('id,name,step_category_ids,parent_id')->select();
        $tree = new \support\Tree('id', 'parent_id', 'children');
        $tree->load($departmentList);
        return $tree->makeParentRefData('parent');
    }

    /**
     * 查询用户所有工序列表
     * @param int $userId
     * @param int $tenantId
     * @param array $ruleIdList
     * @return array
     */
    public function getUserDepartmentStepIdList(int $userId, int $tenantId, array $ruleIdList = [])
    {
        $tenantUserListFilter = ['user_id' => $userId, 'tenant_id' => $tenantId];
        if (count($ruleIdList) > 0) {
            $tenantUserListFilter['role_id'] = ['IN', $ruleIdList];
        }
        $tenantUserIdList = model(TenantUserModel::class)
            ->where($tenantUserListFilter)
            ->field('id')
            ->column('id');
        if (count($tenantUserIdList) === 0) {
            return [];
        }
        $departmentIdList = model(TenantUserDepartmentModel::class)
            ->where(['tenant_user_id' => ['IN', implode(',', $tenantUserIdList)]])
            ->column('department_id');
        if (empty($departmentIdList)) {
            return [];
        }
        return $this->getDepartmentStepIdList($departmentIdList);
    }

    /**
     * 获取部门下人员 合并部门信息
     * @param $param
     * @param bool $includeEmployed
     * @return array|null
     * @throws \Exception
     */
    public function selectDepartmentUserDepartmentInfoMerged($param, bool $includeEmployed)
    {
        $filter = [
            'user.is_system' => 'no',
            'user.active' => 1,
        ];
        if (!empty($param['filter']['tenant_id'])) {
            $filter['tenant_user.tenant_id'] = $param['filter']['tenant_id'];
        }
        if (!$includeEmployed) {
            $filter['tenant_user.status'] = ['NEQ', TenantUserModel::STATUS_UNEMPLOYED];
        }
        $departmentId = $param['filter']['department_id'] ?? 0;
        $usernameFilter = $param['filter']['user_name'] ?? null;
        $phoneOrName = $param['filter']['name_or_phone'] ?? null;
        $userIdFilter = $param['filter']['user_id'] ?? 0;
        $roleCodes = $param['filter']['role_code'] ?? "";
        $roleCodes = explode(',', $roleCodes);
        $stepCategoryId = $param['filter']['department.step_category_ids'] ?? null;
        if (!empty($stepCategoryId)) {
            $filter['department.step_category_ids'] = $stepCategoryId;
        }

        if ($departmentId) {
            $filter['department.id'] = $departmentId;
        }
        if ($userIdFilter) {
            $filter['tenant_user.user_id'] = $userIdFilter;
        }
        // 角色筛选
        if (count($roleCodes) > 0) {
            $roles = model(RoleModel::class)->where(['code' => ['IN', implode(',', $roleCodes)]])->field("id")->select();
            $roleIds = array_column($roles, 'id', 'id');
            if (count($roles) > 0) {
                $filter["role.id"] = ["IN", implode(',', $roleIds)];
            }
        }

        if (!empty($phoneOrName)) {
            $filter[] = [
                "user.name" => $phoneOrName,
                "user.phone" => $phoneOrName,
                "_logic" => "OR",
            ];
        }
        if (!empty($usernameFilter)) {
            $filter[] = [
                "user.name" => $usernameFilter,
            ];
        }
        $departmentStepCategoryIds = $param['department_step_category_ids'] ?? '';
        if (!empty($departmentStepCategoryIds)) {
            $departmentStepCategoryIdData = [];
            $departmentStepCategoryIdList = explode(',', $departmentStepCategoryIds);
            $findInSetField = 'department.step_category_ids';
            foreach ($departmentStepCategoryIdList as $departmentStepCategoryIdItem) {
                $departmentStepCategoryIdData[] = "FIND_IN_SET('{$departmentStepCategoryIdItem}' , {$findInSetField})";
            }
            $departmentStepCategoryIdData['_logic'] = 'OR';
            $filter[] = $departmentStepCategoryIdData;
        }

        $tenantUserModel = model(TenantUserModel::class);

        if (array_key_exists('page', $param)) {
            $page = join(',', $param['page']);
        } else {
            $maxPageSize = C("database.database_max_select_rows");
            $page = "1, {$maxPageSize}";
        }

        // 获取总行数
        $total = $tenantUserModel
            ->alias('tenant_user')
            ->join("user ON user.id = tenant_user.user_id")
            ->join('tenant_user_department on tenant_user_department.tenant_user_id = tenant_user.id', 'LEFT')
            ->join('tenant_user_role on tenant_user_role.tenant_user_id = tenant_user.id', 'LEFT')
            ->join("role ON role.id = tenant_user_role.role_id", 'LEFT')
            ->join("department ON department.id = tenant_user_department.department_id", 'LEFT')
            ->where($filter)->field('count(DISTINCT tenant_user.user_id) as count')->find();

        $total = $total['count'];
        $res = [];
        if ($total > 0) {
            $fields = [
                'tenant_user.id', 'tenant_user.user_id', 'tenant_user.tenant_id', 'tenant_user.status',
                'tenant_user.created', 'user.name', 'user.phone', 'user.email',
                'tenant_user.tenant_position_id',
            ];
            $res = $tenantUserModel
                ->join("user ON user.id=tenant_user.user_id")
                ->join('tenant_user_department on tenant_user_department.tenant_user_id = tenant_user.id', 'LEFT')
                ->join('tenant_user_role on tenant_user_role.tenant_user_id = tenant_user.id', 'LEFT')
                ->join("role ON role.id = tenant_user_role.role_id", 'LEFT')
                ->join("department ON department.id = tenant_user_department.department_id", 'LEFT')
                ->field($fields)
                ->where($filter)
                ->page($page)
                ->group('tenant_user.id')
                ->order('tenant_user.created desc')
                ->select();
            if (count($res) > 0) {
                $userIdList = array_column($res, 'user_id');
                $tenantUserIdList = array_column($res, 'id');
                $departmentAndRoleInfoMap = TenantUserService::getInstance()->getTenantUserListDepartmentRole($tenantUserIdList);
                // 通过用户信息合并
                $avatarMap = UserService::getInstance()->getUserAvatar($userIdList);

                foreach ($res as &$item) {
                    $userId = $item['user_id'];
                    $item['avatar'] = $avatarMap[$userId] ?? null;
                    $item['department_info'] = $item['role_info'] = [];
                    if (isset($departmentAndRoleInfoMap[$item['id']])) {
                        $item = array_merge($item, $departmentAndRoleInfoMap[$item['id']]);
                    }
                }
            }
        }

        return [
            "total" => $total,
            "rows" => $res,
        ];
    }

    /**
     * 获取当前租户基本信息
     * @param $currentTenantId
     * @return array
     */
    public function getCurrentTenantInfo($currentTenantId)
    {
        $res['tenant'] = model(TenantModel::class)->field('id,name,status,created,role')->find($currentTenantId);
        $tenantAuth = model(TenantAuthenticationModel::class)->where(['tenant_id' => $currentTenantId, 'status' => 'active'])->find();
        $res['tenant']['auth'] = (bool)$tenantAuth;
        $res['tenant_auth'] = model(TenantAuthenticationModel::class)->field('id,tenant_id,legal_person_name,fdd_auth_status,status,company_name')->where(['tenant_id' => $currentTenantId])->find();
        return $res;
    }

    /**
     * 查询乙方权限
     * @return array|false|string[]
     */
    public function selectToTenantRole()
    {
        $optionsModel = model(OptionsModel::class);
        $toTenantRole = $optionsModel->where(['name' => 'to_tenant_role_settings'])->find();
        if ($toTenantRole) {
            $roleConfig = json_decode($toTenantRole['config'], true);
            return explode(',', $roleConfig['resource_ids']);
        } else {
            return [];
        }
    }

    /**
     * 设置乙方权限
     * @param $data
     * @return array|bool|int
     * @throws \Exception
     */
    public function setToTenantRole($data)
    {
        $optionModel = model(OptionsModel::class);
        $tenantOption = $optionModel->where(['name' => 'to_tenant_role_settings'])->find();
        $setResource = [];
        foreach ($data['resource_ids'] as $resource_id) {
            $setResource[] = $resource_id;
        }
        if (empty($tenantOption)) {
            $addOptions = [
                'name' => 'to_tenant_role_settings',
                'type' => 'system',
                'config' => ['resource_ids' => implode(',', $setResource)],
            ];
            return $optionModel->addItem($addOptions);
        } else {
            $setResource = implode(',', $setResource);
            return $optionModel->execute("UPDATE options SET config = JSON_SET(IFNULL(config, '{}'), '$.\"resource_ids\"', '$setResource') where id = {$tenantOption['id']}");
        }
    }

    /**
     * 获取工单归属有关的租户信息
     * @param $param
     * @param $tenantId
     * @return array
     */
    public function getWorkOrderRelatedTenant($param, $tenantId)
    {
        $belongType = $param['filter']['belong_type'];
        $currentTenantType = $param['filter']['current_tenant_type'];
        $currentTenant = model(TenantModel::class)->where(['id' => $tenantId])->find();
        // 当前租户类型是甲方无需查询工单归属类型
        if ($currentTenantType == 'inside') {
            // 甲方可以拉所有外包出去的项目租户的商务制片，不区分情况
            $projectId = $param['filter']['belong_project_id'] > 0 ? $param['filter']['belong_project_id'] : $param['filter']['project_id'];
            $downStreamProjects = Request::connection()
                ->setHeader([
                    'X-Userinfo' => request()->getXUserInfo(),
                ])
                ->setServerHost('teamones-saas')
                ->setRoute('project/base_select')
                ->setBody([
                    'param' => [
                        'filter' => [
                            'belong_project_id' => $projectId,
                        ],
                        "fields" => "project.id,project.tenant_id,project.belong_project_id,project.name",
                    ],
                ])
                ->setMethod('POST')
                ->request()['data'];
            $downStreamProjectTenantIds = [];
            foreach ($downStreamProjects['rows'] as $downStreamProject) {
                $downStreamProjectTenantIds[] = $downStreamProject['project']['tenant_id'];
            }
            if (!empty($downStreamProjectTenantIds)) {
                $res['to_tenant'] = model(TenantModel::class)->field('id,name,status,created')->where(['id' => ['IN', $downStreamProjectTenantIds], 'status' => 'active'])->select();
            }
            $currentTenantGroupIds = model(TenantGroupMemberModel::class)->where(['tenant_id' => $tenantId])->column("tenant_group_id");
            if (!empty($currentTenantGroupIds)) {
                $res['current_relate_tenant_group'] = model(TenantGroupModel::class)->field("id,name")->where(['id' => ['IN', $currentTenantGroupIds], 'status' => 'active'])->select();
            }
        } else if (($currentTenantType == 'tenant_group_outside' && $belongType == 'tenant_group_outside') || ($currentTenantType == 'outside' && $belongType == 'outside')) {
            // 只有工单归属是集团内乙方或者供应商乙方的时候，才会需要返回甲方的租户信息
            $belongProjectTenantId = $param['filter']['belong_project_tenant_id'];
            $res['from_tenant'] = model(TenantModel::class)->field('id,name,status,created')->where(['id' => $belongProjectTenantId])->find();
        }
        $res['current_tenant'] = $currentTenant;
        return $res;
    }

    /**
     * 创建团队
     * @param $userId
     * @param $params
     * @return array|bool
     * @throws \Exception|\Throwable
     */
    public function registerTenant($userId, $params)
    {
        $data = $params['data'];
        $userInfo = model(UserModel::class)->field(['id', 'phone'])->where(['id' => $userId])->find();
        if (empty($userInfo)) {
            throw_strack_exception('User does not exist.', ErrorCode::USER_NOT_EXIST);
        }
        // 1. 校验验证码，如果创建团队的手机号码不是当前用户的手机号码就需要校验验证码
        $smsService = new SMSService();
        if (!$smsService->checkChangePhoneSMSCode(SmsVerifyModel::TYPE_REGISTER, $data['phone'], $userInfo['phone'], $data['sms_code'] ?? '')) {
            throw_strack_exception('Invalid SMS verification code.', ErrorCode::SMS_VERIFICATION_CODE_ERROR);
        }

        // 2. 一个用户只能创建一个团队（激活状态）
        $myCreatedTenantInfo = model(TenantModel::class)->where(['created_by' => $userId, 'status' => TenantModel::STATUS_ACTIVE])->field(['id', 'name', 'status'])->select();
        if (!empty($myCreatedTenantInfo)) {
            throw_strack_exception('You have already created a team, you can only create one tenant.', ErrorCode::ONLY_CREATE_ONE_TENANT);
        }

        $tenantModel = model(TenantModel::class);
        $tenantModel->startTrans();

        try {
            // 3. 创建团队
            $tenantInfo = $this->addTenant($userId, $data['company_name']);
            if (empty($tenantInfo)) {
                throw_strack_exception('create tenant fail.', ErrorCode::CREATE_TENANT_FAIL);
            }

            // 4. 身份证信息保存到企业信息认证表的法人信息中tenant_authentication
            $tenantAuthenticationService = new TenantAuthenticationService();
            $addTenantAuthRes = $tenantAuthenticationService->saveTenantAuthentication($tenantInfo['id'], $data);
            if (empty($addTenantAuthRes)) {
                throw_strack_exception('save tenant authentication fail.', ErrorCode::SAVE_TENANT_AUTHENTICATION_FAIL);
            }

            $tenantModel->commit();
            return $tenantInfo;
        } catch (\Throwable $e) {
            $tenantModel->rollback();
            throw $e;
        }
    }

    /**
     * 增加工序级别
     * @param $tenantId
     * @param $serviceCategory
     * @return bool|int|string
     * @throws \Exception
     */
    private function addStepCategoryLevel($tenantId, $serviceCategory)
    {
        $res = [];
        // 获取默认的工序级别
        $levelOptionInfo = model(DataSourceModel::class)
            ->where(['code' => 'tenant_authentication_level_options', 'is_default' => DataSourceModel::IS_DEFAULT_YES])
            ->field('key')
            ->find();
        if (empty($levelOptionInfo)) {
            return false;
        }
        $levelData = [];
        foreach ($serviceCategory as $item) {
            $levelData[] = [
                'tenant_id' => $tenantId,
                'step_category_id' => $item['id'],
                'step_category_name' => $item['name'],
                'step_category_code' => $item['code'],
                'level' => $levelOptionInfo['key'],
                'created' => time(),
                'updated' => time(),
                'created_by' => fill_created_by()
            ];
        }
        if (!empty($levelData)) {
            $res = model(TenantStepCategoryLevelModel::class)->addAll($levelData);
        }
        return $res;
    }

    /**
     * 添加团队信息
     * @param $userId [用户id]
     * @param $companyName [团队名称]
     * @return array|bool
     * @throws \Exception
     */
    public function addTenant($userId, $companyName)
    {
        $tenantModel = model(TenantModel::class);
        // 公司不存在 就创建公司
        $tenant = $tenantModel->addItem([
            "name" => $companyName,
            "status" => TenantModel::STATUS_ACTIVE,
            "created_by" => $userId,
        ]);
        if ($tenant === false) {
            throw_strack_exception($tenantModel->getError(), ErrorCode::CREATE_TENANT_FAIL);
        }

        // 给租户新增默认部门
        $departmentModel = model(DepartmentModel::class);
        $department = $departmentModel->addItem([
            "name" => "默认部门",
            "tenant_id" => $tenant['id'],
        ]);
        if ($department === false) {
            throw_strack_exception("add default department fail", ErrorCode::DEPARTMENT_CREATE_FAILURE);
        }
        // 加入租户，默认角色设置为“商务制作”和“租户管理员”
        $roles = model(RoleModel::class)->where(['code' => ['in', [RoleModel::BUSINESS_PRODUCER_CODE, RoleModel::TENANT_ADMINISTRATOR_CODE]]])->field(['id'])->select();
        if (empty($roles)) {
            throw_strack_exception("missing business_producer or admin role", ErrorCode::MISSING_BUSINESS_PRODUCER_ROLE);
        }
        $rolesIds = array_column($roles, 'id');
        $this->addTenantUser($userId, $tenant['id'], $rolesIds, $department['id']);

        return $tenant;
    }

    /**
     * 加入租户并激活
     * @param $userId
     * @param $tenantId
     * @param $roleIds
     * @param $departmentId
     * @return array|false|mixed|string|null
     * @throws \Exception
     */
    public function addTenantUser($userId, $tenantId, $roleIds, $departmentId)
    {
        $tenantUserModel = model(TenantUserModel::class);

        // 判断是否存在激活的租户用户，将其设置未激活
        $activeTenantUserIds = $tenantUserModel->where(['status' => TenantUserModel::STATUS_ACTIVE, 'user_id' => $userId])->field('id')->column('id');
        if (!empty($activeTenantUserIds)) {
            $tenantUserModel->where(['id' => implode(',', $activeTenantUserIds)])->save(['status' => TenantModel::STATUS_INVALID]);
        }

        // 添加租户用户，状态为激活状态
        $tenantUserRes = $tenantUserModel->addItem([
            "tenant_id" => $tenantId,
            "user_id" => $userId,
            "status" => TenantUserModel::STATUS_ACTIVE
        ]);
        if ($tenantUserRes === false) {
            throw_strack_exception("add tenant user fail", ErrorCode::ADD_TENANT_USER_FAIL);
        }

        $tenantUserId = $tenantUserRes['id'];
        $addTenantUserDepartmentRes = model(TenantUserDepartmentModel::class)->addItem([
            'tenant_user_id' => $tenantUserId,
            'department_id' => $departmentId,
            'created_by' => $userId
        ]);
        if ($addTenantUserDepartmentRes === false) {
            throw_strack_exception("add tenant user department fail", ErrorCode::ADD_TENANT_USER_FAIL);
        }
        // 角色可能有多个
        $addUserRoleData = [];
        foreach ($roleIds as $roleId) {
            $addUserRoleData[] = [
                'tenant_user_id' => $tenantUserId,
                'role_id' => $roleId
            ];
        }
        $addUserRoleRes = model(TenantUserRoleModel::class)->addAll($addUserRoleData);
        if ($addUserRoleRes === false) {
            throw_strack_exception("add user role fail", ErrorCode::ADD_TENANT_USER_FAIL);
        }

        return $tenantUserRes;

    }

    /**
     * 删除团队
     * @param $params
     * @return array
     * @throws \Exception|\Throwable
     */
    public function deleteTenant($params)
    {
        // 校验参数
        if (empty($params['id']) || count($params['id']) > 1000) {
            return [];
        }
        $tenantIds = $params['id'];
        $tenantModel = model(TenantModel::class);

        // 1. 检查团队存不存在
        $tenantIno = $tenantModel->field(['id'])->where(['id' => $tenantIds])->find();

        if (empty($tenantIno)) {
            throw_strack_exception("Tenant does not exist", ErrorCode::TENANT_NOT_EXIST);
        }

        // 2. 判断团队下是否还有用户
        $tenantUserInfo = model(TenantUserModel::class)
            ->field('id')
            ->where(['tenant_id' => $tenantIds])
            ->find();
        if (!empty($tenantUserInfo)) {
            throw_strack_exception("The tenant still has users, please remove them first", ErrorCode::TENANT_HAS_USERS);
        }

        $tenantModel->startTrans();

        try {
            // 3. 删除团队
            $resData = $tenantModel->deleteItem(['id' => $tenantIds]);
            if ($resData === false) {
                throw_strack_exception("Delete tenant fail", ErrorCode::TENANT_DELETE_FAIL);
            }

            // 4. 删除团队下的部门
            $delDepartmentRes = model(DepartmentModel::class)->deleteItem(['tenant_id' => $tenantIds]);
            if ($delDepartmentRes === false) {
                throw_strack_exception("Delete department fail", ErrorCode::DEPARTMENT_DELETE_FAIL);
            }
            $tenantModel->commit();
        } catch (\Throwable $e) {
            $tenantModel->rollback();
            throw $e;
        }

        return [];
    }

    /**
     * 解散团队
     * @param $userId
     * @param $params
     * @return array|bool
     * @throws \Exception|\Throwable
     */
    public function disband($userId, $params)
    {
        $tenantId = $params['tenant_id'];
        // 1. 获取用户信息
        $userInfo = model(UserModel::class)->field(['id', 'phone'])->where(['id' => $userId])->find();
        if (empty($userInfo)) {
            throw_strack_exception('User does not exist.', ErrorCode::USER_NOT_EXIST);
        }

        // 2. 校验验证码
        $smsService = new SMSService();
        if (!$smsService->checkSMSCode(SmsVerifyModel::TYPE_DISBAND, $userInfo['phone'], $params['sms_code'])) {
            throw_strack_exception('Invalid SMS verification code.', ErrorCode::SMS_VERIFICATION_CODE_ERROR);
        }

        // 3. 校验是否为自己创建的团队
        $tenantInfo = model(TenantModel::class)->where(['id' => $tenantId, 'created_by' => $userId])->field(['id'])->find();
        if (empty($tenantInfo)) {
            throw_strack_exception('Can only disband tenant created by oneself.', ErrorCode::TENANT_NOT_EXIST);
        }

        $tenantModel = model(TenantModel::class);
        $tenantModel->startTrans();
        try {
            // 4. 将当前解散团队的租户用户状态置为无效，获取未激活的租户用户，将其激活
            $this->switchTenantUserStatus($userId, $tenantId);

            // 5. 解散团队
            $res = $tenantModel->where(['id' => $tenantId])->save(['status' => TenantModel::STATUS_INVALID]);
            if ($res === false) {
                throw_strack_exception('Disband tenant fail.', ErrorCode::TENANT_DISBAND_FAIL);
            }
            $tenantModel->commit();
        } catch (\Throwable $e) {
            $tenantModel->rollback();
            throw $e;
        }

        return $res;
    }

    /**
     * 将当前解散团队的租户用户状态置为无效，获取未激活的租户用户，将其激活
     * @param $userId
     * @param $tenantId
     * @throws \Exception
     */
    private function switchTenantUserStatus($userId, $tenantId)
    {
        // 获取未激活的租户用户，获取一个未激活用户，将其激活
        $tenantUserModel = model(TenantUserModel::class);
        $invalidTenantUser = $tenantUserModel
            ->join('tenant ON tenant.id = tenant_user.tenant_id')
            ->where([
                'tenant.status' => TenantModel::STATUS_ACTIVE,
                'tenant_user.user_id' => $userId,
                'tenant_user.status' => TenantUserModel::STATUS_INVALID,
            ])
            ->field(['tenant_user.id'])->find();
        if (!empty($invalidTenantUser)) {
            $tenantUserModel->where(['id' => $invalidTenantUser['id']])->save(['status' => TenantModel::STATUS_ACTIVE]);
        }

        $currentTenantUser = $tenantUserModel
            ->where([
                'user_id' => $userId,
                'tenant_id' => $tenantId,
            ])
            ->field(['id'])->find();
        // 将当前租户用户状态设置无效
        if (!empty($currentTenantUser)) {
            $tenantUserModel->where(['id' => $currentTenantUser['id']])->save(['status' => TenantModel::STATUS_INVALID]);
        }
    }

    /**
     * 更新团队信息
     * @param $params
     * @return array|bool
     * @throws \Exception
     */
    public function updateBaseInfo($params)
    {
        $tenantModel = model(TenantModel::class);
        $tenantInfo = $tenantModel->field(['id', 'created_by'])->where(['id' => $params['id']])->find();
        if (empty($tenantInfo)) {
            throw_strack_exception('Tenant does not exist.', ErrorCode::TENANT_NOT_EXIST);
        }

        // 如果激活团队，需要校验是否已创建过团队，个用户只能创建一个团队(激活状态的团队)
        if ($params['status'] == TenantModel::STATUS_ACTIVE) {
            $activeTenantInfo = $tenantModel->field(['id'])->where(['created_by' => $tenantInfo['created_by'], 'status' => TenantModel::STATUS_ACTIVE, 'id' => ['NEQ', $params['id']]])->find();
            if (!empty($activeTenantInfo)) {
                throw_strack_exception('Only one activated tenant can exist', ErrorCode::ONLY_CREATE_ONE_TENANT);
            }
        }

        $res = $tenantModel->modifyItem($params);
        if ($res === false) {
            throw_strack_exception($tenantModel->getError(), ErrorCode::TENANT_UPDATE_FAIL);
        }
        return $res;
    }

    /**
     * 更新团队信息(服务类别、法人信息)
     * @param $params
     * @return array
     * @throws \Exception|\Throwable
     */
    public function updateInfo($params)
    {
        $tenantId = $params['id'];
        // 1. 获取企业认证信息
        $tenantAuthenticationModel = model(TenantAuthenticationModel::class);
        $authInfo = $tenantAuthenticationModel->where(['tenant_id' => $tenantId])->find();
        if (empty($authInfo)) {
            throw_strack_exception('tenant authentication does not exist.', ErrorCode::DATA_NOT_EXIST);
        }

        // 2. 校验验证码，如果手机号码不是更新之前的手机号码就需要校验验证码
        $smsService = new SMSService();
        if (!$smsService->checkChangePhoneSMSCode(SmsVerifyModel::TYPE_CHANGE_PHONE, $params['phone'], $authInfo['legal_phone'], $params['sms_code'] ?? '')) {
            throw_strack_exception('Invalid SMS verification code.', ErrorCode::SMS_VERIFICATION_CODE_ERROR);
        }

        // 3. 校验是否已认证
        if ($authInfo['fdd_auth_status'] == TenantAuthenticationModel::FDD_AUTH_STATUS_PASS) {
            throw_strack_exception('tenant has been authenticated.', ErrorCode::TENANT_HAS_BEEN_AUTHENTICATION);
        }

        $tenantAuthenticationModel->startTrans();
        try {
            // 4. 更新法人信息
            $tenantAuthenticationService = new TenantAuthenticationService();
            $addTenantAuthRes = $tenantAuthenticationService->saveTenantAuthentication($tenantId, $params);
            if (empty($addTenantAuthRes)) {
                throw_strack_exception('save tenant authentication fail.', ErrorCode::SAVE_TENANT_AUTHENTICATION_FAIL);
            }

            // 5. 更新服务类型等级
            $this->dealStepCategoryLevel($tenantId, $params['service_category'], json_decode(empty($authInfo['service_category']) ? '{}' : $authInfo['service_category'], true));
            $tenantAuthenticationModel->commit();
        } catch (\Throwable $e) {
            $tenantAuthenticationModel->rollback();
            throw $e;
        }

        return [];
    }

    /**
     * 处理工序类别等级
     * @param int $tenantId 团队id
     * @param array $newServiceCategory 提交的服务类别
     * @param array $oldServiceCategory 更新前的服务类别
     * @throws \Exception
     */
    public function dealStepCategoryLevel(int $tenantId, array $newServiceCategory, array $oldServiceCategory = [])
    {
        // 获取工序类别id
        $newServiceCategoryIds = array_column($newServiceCategory, 'id');
        $oldServiceCategoryIds = array_column($oldServiceCategory, 'id');

        // 找出新增和删除的工序类别id
        $addServiceCategoryIds = array_diff($newServiceCategoryIds, $oldServiceCategoryIds);
        $deleteServiceCategoryIds = array_diff($oldServiceCategoryIds, $newServiceCategoryIds);

        // 找出新增的工序类别
        $addServiceCategory = array_filter($newServiceCategory, function ($item) use ($addServiceCategoryIds) {
            return in_array($item['id'], $addServiceCategoryIds);
        });

        // 添加工序类别等级
        if (!empty($addServiceCategory)) {
            $addRes = $this->addStepCategoryLevel($tenantId, $addServiceCategory);
            if (empty($addRes)) {
                throw_strack_exception('add step category level fail.', ErrorCode::SERVICE_CATEGORY_SAVE_FAIL);
            }
        }

        // 删除工序类别等级
        if (!empty($deleteServiceCategoryIds)) {
            model(TenantStepCategoryLevelModel::class)
                ->where(['tenant_id' => $tenantId, 'step_category_id' => ['IN', implode(',', $deleteServiceCategoryIds)]])
                ->delete();
        }

        // 更新供应商服务类型
        $this->saveSupplierStepCategory($tenantId, $newServiceCategory);
    }

    /**
     * 保存供应商服务类型
     * @param $tenantId
     * @param $serviceCategory
     * @return void
     * @throws \Exception
     */
    public function saveSupplierStepCategory($tenantId, $serviceCategory)
    {
        $supplierData = model(SupplierModel::class)->where(['from_tenant_id' => $tenantId, 'type' => 'outside'])->field('id')->select();
        $supplierIdList = array_column($supplierData, 'id');
        $stepCategoryIdList = array_column($serviceCategory, 'id');
        if (!empty($supplierIdList)) {
            model(SupplierModel::class)->where(['id' => ['IN', implode(',', $supplierIdList)]])->save(['step_category_ids' => implode(',', $stepCategoryIdList)]);
        }
    }
}
